/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.web;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

import java.sql.*;

import nfse.*;
import nfse.gui.query.QueryResult;
import nfse.gui.record.FlexRecord;

import nfse.gui.server.GUIRecordFactory;
import nfse.gui.server.QueryServiceImpl;

public class Export extends HttpServlet {
    
    final QueryServiceImpl qsi = new QueryServiceImpl();
    
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            response.setContentType("application/base64");
            out = response.getWriter();
            
            String action = request.getParameter("action");
            if (action != null && action.equals("timeline")) {
                timeline(request, out);
                return;
            }
            
            String queryID = request.getParameter("queryid");

            String where = request.getParameter("where");
            if (where == null)
                where = "";
            where = NetFSEUtil.convertFromHex(where);

            String orderBy = request.getParameter("orderby");
            if (orderBy == null)
                orderBy = "";

            String colHeader = request.getParameter("colheader");
            if (colHeader == null || colHeader.length() == 0)
                colHeader = "YES";
            colHeader = colHeader.toUpperCase();

            int type = Integer.parseInt(request.getParameter("type"));
            

            GUIRecordFactory factory = (GUIRecordFactory)NetFSE.getRecordFactory(type);
            NetFSERecord rec = (NetFSERecord)factory.generate();

            if (colHeader.equals("YES")) {
                out.println(factory.getCSVColNames());
            }

            Statement s1 = qsi.createResultStatement();

            String table = queryID + "_" + type;
            String sql = "select * from " + queryID + ", " + table + " where Type_ID=" + type + " and " + queryID
                    + ".ID=" + queryID + "_" + type + ".ID ";
            if (where.length() > 0) {
                sql += " and (" + where + ") ";
            }
            if (orderBy.length() > 0) {
                sql += " order by " + orderBy;
            }

            // out.println(sql);

            int idx = sql.indexOf("*");

            String sql2 = sql.substring(0, idx) + " count(*) as a " + sql.substring(idx + 1);
            ResultSet rs = s1.executeQuery(sql2);
            rs.next();
            int count = rs.getInt("a");
            int itterations = count / 10000 + 1;

            for (int i = 0; i < itterations; i++) {

                // Statement s2 = c.createStatement();
                // String sql = "select * from " + queryID + " where Type_ID=" +
                // type;
                int offset = i * 10000 + 1;
                if (i == 0)
                    offset--;
                String tempSQL = sql + " limit 10000 offset " + offset;
                rs = s1.executeQuery(tempSQL);
                // out.println(sql);
                while (rs.next()) {
                    int sensor = rs.getInt("Sensor_ID");
                    String line = convertFromHex(rs.getString("Record"));
                    NetFSERecord temp = (NetFSERecord)factory.generate(line, sensor);
                    out.println(factory.toCSV(temp));
                }
                rs.close();

            }
            out.flush();
            out.close();
            s1.close();
           
        } catch (Exception E) {
            E.printStackTrace(out);
        }
    }

    private static String convertFromHex(String line) {
        byte[] bytes = new byte[line.length() / 2];
        for (int i = 0; i < bytes.length; i++)
            bytes[i] = (byte) Integer.parseInt(line.substring(i * 2, i * 2 + 2), 16);
        return new String(bytes);
    }

    public void timeline(HttpServletRequest request,PrintWriter out ) {
        try {
            
            
            String queryID = request.getParameter("queryid");
            String typeStr = request.getParameter("types");
            String[] typeStrs = typeStr.split(" +");
            int[] types = new int[typeStrs.length];
            String[] where = new String[types.length];
            for (int i = 0; i < types.length; i++) {
                types[i] = Integer.parseInt(typeStrs[i]);
                where[i] = request.getParameter("where" + types[i]);
                if (where[i] == null)
                    where[i] = "";
                if (where[i].length() > 0)
                    where[i] = convertFromHex(where[i]);
            }
            String nStr = request.getParameter("n");
            int n = -1;
            if (nStr == null || nStr.length() ==0)
                n = 100;
            else
                n = Integer.parseInt(nStr);
            if (n <= 0)
                n = 100;
            
            QueryResult[] qrs = new QueryResult[types.length];
            int[] startTSIdxs = new int[types.length];
            int[] srcipIdxs = new int[types.length];
            int[] dstipIdxs = new int[types.length];
            int[] srcportIdxs = new int[types.length];
            int[] dstportIdxs = new int[types.length];
            int[] protocolIdxs = new int[types.length];
            int[] recordIdxs = new int[types.length];
            for (int i = 0; i < types.length; i++) {
                // System.out.println("type=" + types[i] + ", where=" +
                // where[i]);
                qrs[i] = qsi.get(queryID, n, 0, types[i], where[i], "startts asc");
                startTSIdxs[i] = -1;
                srcipIdxs[i] = -1;
                dstipIdxs[i] = -1;
                srcportIdxs[i] = -1;
                dstportIdxs[i] = -1;
                protocolIdxs[i] = -1;
                recordIdxs[i] = 0;
                if (qrs[i] != null && qrs[i].flexRecordGroup != null) {
                    startTSIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("startts");
                    srcipIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("srcip");
                    dstipIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("dstip");
                    dstportIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("dstport");
                    srcportIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("srcport");
                    protocolIdxs[i] = qrs[i].flexRecordGroup.getFieldIdx("protocol");
                }
            }
            int idx = 0;
            while (idx < n) {
                Timestamp minTS = null;
                int minIdx = -1;
                for (int x = 0; x < qrs.length; x++) {
                    if (qrs[x] != null && qrs[x].flexRecordGroup != null) {
                        FlexRecord rec = qrs[x].flexRecordGroup.getRecord(recordIdxs[x]);
                        if (rec != null && startTSIdxs[x] != -1) {
                            rec.startTSIdx = startTSIdxs[x];
                            rec.dstipIdx = dstipIdxs[x];
                            rec.srcipIdx = srcipIdxs[x];
                            rec.srcportIdx = srcportIdxs[x];
                            rec.dstportIdx = dstportIdxs[x];
                            rec.protoIdx = protocolIdxs[x];
                            String tsStr = rec.values[startTSIdxs[x]];
                            Timestamp ts = Timestamp.valueOf(tsStr);
                            if (minTS == null || ts.before(minTS)) {
                                minTS = ts;
                                minIdx = x;
                            }
                        }
                    }
                }
                if (minTS == null) {
                    idx = n;
                } else {

                    FlexRecord rec = qrs[minIdx].flexRecordGroup.getRecord(recordIdxs[minIdx]);
                    rec.colNames = qrs[minIdx].flexRecordGroup.getColumnNames();
                    
                    out.println(rec.toString());
                    // System.out.println(rec.toString());
                }
                idx++;
            }
            out.flush();
            out.close();
        } catch (Exception E) {
            E.printStackTrace();
        }
    }
    
}
